﻿using System;
using System.IO;
using System.Collections.Generic;
using System.Text;
using NUnit.Framework;
using NU=NUnit.Framework;
using Stauffware.Common.Core;
using Stauffware.Common.Console;
//using log4net;

namespace UnitTests
{
	// To be added:
	//		break-before characters
	//		break-after characters
	//		negative tests
	//		very long sequence of characters with no breaks

	public class FrmttngTxtWrtr_UnitTests
	{
		[SetUp]
		public static void ClassSetup ( )
		{
		//	log4net.Config.XmlConfigurator.Configure();
		}

		#region Miscellany

		[TestCase(80, "", "")]
		[TestCase(20, "a", "a")]

		public void Miscellany (int width, string input, string expOutput)
		{
			DoOneTest(width, input, expOutput);
		}

		#endregion

		#region Long Words (no word breaks)

		//            0         1         2         3         4         5         6         7         8
		//            012345678901234567890123456789012345678901234567890123456789012345678901234567890
		[TestCase(50, "AaBbCcDdEeFfGgHhIiJjKkLlMmNnOoPpQqRrSsTtUuVvWwXxYyZz",
					  "AaBbCcDdEeFfGgHhIiJjKkLlMmNnOoPpQqRrSsTtUuVvWwXxYy\nZz")]
		[TestCase(18, "AaBbCcDdEeFfGgHhIiJjKkLlMmNnOoPpQqRrSsTtUuVvWwXxYyZz",
					  "AaBbCcDdEeFfGgHhIi\nJjKkLlMmNnOoPpQqRr\nSsTtUuVvWwXxYyZz")]
		[TestCase(50, "Too long: AaBbCcDdEeFfGgHhIiJjKkLlMmNnOoPpQqRrSsTtUuVvWwXxYyZz",
					  "Too long: AaBbCcDdEeFfGgHhIiJjKkLlMmNnOoPpQqRrSsTt\nUuVvWwXxYyZz")]
		[TestCase(40, "Too AaBbCcDdEeFfGgHhIiJjKkLlMmNnOoPpQqRrSsTtUuVvWwXxYyZz long!",
					  "Too AaBbCcDdEeFfGgHhIiJjKkLlMmNnOoPpQqRr\nSsTtUuVvWwXxYyZz long!")]

		public void LongWord (int width, string input, string expOutput)
		{
			DoOneTest(width, input, expOutput);
		}

		#endregion

		#region Explicit Newlines

		[TestCase(80, "\n", "\n")]
		[TestCase(80, "\n\n", "\n\n")]
		[TestCase(60, "I am the test", "I am the test")]
		[TestCase(60, "I am the test\n", "I am the test\n")]
		[TestCase(60, "I\nam\nthe\ntest\n", "I\nam\nthe\ntest\n")]
		[TestCase(60, "I am\n\nthe test", "I am\n\nthe test")]

		public void NewLines (int width, string input, string expOutput)
		{
			DoOneTest(width, input, expOutput);
		}

		#endregion

		#region WordBreak

		//            0         1         2         3         4         5         6
		//            0123456789012345678901234567890123456789012345678901234567890

		[TestCase(47, "The quick brown fox jumped over the lazy dogs.",
					  "The quick brown fox jumped over the lazy dogs.")]	

		[TestCase(46, "The quick brown fox jumped over the lazy dogs.",
					  "The quick brown fox jumped over the lazy dogs.")]	

		[TestCase(45, "The quick brown fox jumped over the lazy dogs.",
					  "The quick brown fox jumped over the lazy \ndogs.")]	

		[TestCase(41, "The quick brown fox jumped over the lazy dogs.",
					  "The quick brown fox jumped over the lazy \ndogs.")]	

		[TestCase(40, "The quick brown fox jumped over the lazy dogs.",
					  "The quick brown fox jumped over the lazy\ndogs.")]	

		[TestCase(39, "The quick brown fox jumped over the lazy dogs.",
					  "The quick brown fox jumped over the \nlazy dogs.")]	

		[TestCase(37, "The quick brown fox jumped over the lazy dogs.",
					  "The quick brown fox jumped over the \nlazy dogs.")]	

		[TestCase(36, "The quick brown fox jumped over the lazy dogs.",
					  "The quick brown fox jumped over the \nlazy dogs.")]	

		[TestCase(35, "The quick brown fox jumped over the lazy dogs.",
					  "The quick brown fox jumped over the\nlazy dogs.")]	

		[TestCase(34, "The quick brown fox jumped over the lazy dogs.",
					  "The quick brown fox jumped over \nthe lazy dogs.")]	

		[TestCase(47, "The quick brown fox jumped over the lazy dogs.\n",
					  "The quick brown fox jumped over the lazy dogs.\n")]		

					//01234567890123456789012345678901234567890123456
		[TestCase(46, "The quick brown fox jumped over the lazy dogs.\n",
					  "The quick brown fox jumped over the lazy dogs.\n")]

		[TestCase(45, "The quick brown fox jumped over the lazy dogs.\n",
					  "The quick brown fox jumped over the lazy \ndogs.\n")]	

		[TestCase(41, "The quick brown fox jumped over the lazy dogs.\n",
					  "The quick brown fox jumped over the lazy \ndogs.\n")]

					//01234567890123456789012345678901234567890
		[TestCase(40, "The quick brown fox jumped over the lazy dogs.\n",
					  "The quick brown fox jumped over the lazy\ndogs.\n")]	

		[TestCase(39, "The quick brown fox jumped over the lazy dogs.\n",
					  "The quick brown fox jumped over the \nlazy dogs.\n")]	

					//0123456789012345678901234567890123456
		[TestCase(36, "The quick brown fox jumped over the lazy dogs.\n",
					  "The quick brown fox jumped over the \nlazy dogs.\n")]

		[TestCase(37, "The quick brown fox jumped over the lazy dogs.\n",
					  "The quick brown fox jumped over the \nlazy dogs.\n")]	

		[TestCase(35, "The quick brown fox jumped over the lazy dogs.\n",
					  "The quick brown fox jumped over the\nlazy dogs.\n")]	

		[TestCase(34, "The quick brown fox jumped over the lazy dogs.\n",
					  "The quick brown fox jumped over \nthe lazy dogs.\n")]

		[TestCase(17, "The quick brown fox jumped over the lazy dogs.\n",
					  "The quick brown \nfox jumped over \nthe lazy dogs.\n")]

		[TestCase(17, "The quick brown fox jumped over the lazy dogs.",
					  "The quick brown \nfox jumped over \nthe lazy dogs.")]

		//            0123456789012345678901234567890123456789012345678901234567890
		//            0         1         2         3         4         5         6

		public void WordBreak (int width, string input, string expOutput)
		{
			DoOneTest(width, input, expOutput);
			//StringWriter sw = new StringWriter();
			//FormattingTextWriter ftw = new FormattingTextWriter(sw, (uint) width);
			//ftw.Write(input);
			//ftw.Flush();
			//string actualOutput = sw.ToString();
			//NU.Assert.AreEqual(expOutput, actualOutput);
		}

		#endregion

		#region SoftHyphen

		//            0         1         2         3
		//            0123456789012345678901234567890
		[TestCase(30, "Let's use polysyllabic words!", "Let's use polysyllabic words!")]
		[TestCase(30, "Let's use po~ly~syl~la~bic words!", "Let's use polysyllabic words!")]
		[TestCase(23, "Let's use po~ly~syl~la~bic words!", "Let's use polysyllabic \nwords!")]
		[TestCase(22, "Let's use po~ly~syl~la~bic words!", "Let's use polysyllabic\nwords!")]
		[TestCase(21, "Let's use po~ly~syl~la~bic words!", "Let's use polysylla-\nbic words!")]
		[TestCase(20, "Let's use po~ly~syl~la~bic words!", "Let's use polysylla-\nbic words!")]
		[TestCase(19, "Let's use po~ly~syl~la~bic words!", "Let's use polysyl-\nlabic words!")]
		[TestCase(18, "Let's use po~ly~syl~la~bic words!", "Let's use polysyl-\nlabic words!")]
		[TestCase(17, "Let's use po~ly~syl~la~bic words!", "Let's use poly-\nsyllabic words!")]
		[TestCase(16, "Let's use po~ly~syl~la~bic words!", "Let's use poly-\nsyllabic words!")]

		public void SoftHyphen (int width, string input, string expOutput)
		{
			input = input.Replace('~', Chars.SoftHyphen.Unicode);
			DoOneTest(width, input, expOutput);
			//StringWriter sw = new StringWriter();
			//FormattingTextWriter ftw = new FormattingTextWriter(sw, (uint) width);
			//ftw.Write(input);
			//ftw.Flush();
			//string actualOutput = sw.ToString();
			//NU.Assert.AreEqual(expOutput, actualOutput);
		}

		#endregion

		#region Prefixes

		private const string Humpty = 
		//  0         1         2         3         4         5         6         7         8
		//  012345678901234567890123456789012345678901234567890123456789012345678901234567890
			"'When I use a word,' Humpty Dumpty said, in rather a scornful tone,\n" + 
			"'it means just what I choose it to mean — neither more nor less.'";

		// LinePrefix, FirstLinePrefix, LineWrapPrefix

		[TestCase("<line>", /*"{1st}",*/ "[wrap]", 100, Humpty,
			"<line>{1st}'When I use a word,' Humpty Dumpty said, in rather a scornful tone,\n" + 
			"<line>{1st}'it means just what I choose it to mean — neither more nor less.'")]

		[TestCase("<line>", /*"{1st}",*/ "[wrap]", 48, Humpty,
			"<line>{1st}'When I use a word,' Humpty Dumpty \n" + 
			"<line>[wrap]said, in rather a scornful tone,\n" + 
			"<line>{1st}'it means just what I choose it to \n" + 
			"<line>[wrap]mean — neither more nor less.'")]

		public void Prefix (string linePrefix, /* string firstLinePrefix, */ string lineWrapPrefix,
							int width, string input, string expOutput)
		{
			StringWriter sw = new StringWriter();
			FormattingTextWriter ftw = new FormattingTextWriter(sw, (uint) width);
			ftw.LinePrefix = linePrefix;
		//	ftw.FirstLinePrefix = firstLinePrefix;
			ftw.PostLineWrap = lineWrapPrefix;
			ftw.Write(input);
			ftw.Flush();
			string actualOutput = sw.ToString();
			NU.Assert.AreEqual(expOutput, actualOutput);
		}

		#endregion

		#region Common Support Methods

		private void DoOneTest (int width, string input, string expOutput)
		{
			StringWriter sw = new StringWriter();
			FormattingTextWriter ftw = new FormattingTextWriter(sw, (uint) width);
			ftw.Write(input);
			ftw.Flush();
			string actualOutput = sw.ToString();
			NU.Assert.AreEqual(expOutput, actualOutput);
		}

		#endregion

	}
}
